﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using Cloud.Core.Dapper;
using Cloud.Core.Data;
using Cloud.Core.Http;
using Cloud.Entity;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.DependencyInjection;
//参考：https://docs.microsoft.com/zh-cn/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
namespace Cloud.UnitOfWork
{
    //每次http请求只会被创建一次，所以工作单元中的Repository在一次请求上下文中也只创建一次
    public class EfUnitOfWork : IUnitOfWork
    {
        private EfDbContext _dbContext;//每次请求上下文只会创建一个
        private bool disposed = false;
        protected Dictionary<Type, object> _repositories;
        public EfUnitOfWork(EfDbContext context)
        {
            this._dbContext = context;
        }
        public int SaveChanges()
        {

            return _dbContext.SaveChanges();
        }
        public async Task<int> SaveChangesAsync()
        {
            return await _dbContext.SaveChangesAsync();
        }
      

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    if (_repositories != null)
                    {
                        _repositories.Clear();
                    }
                    _dbContext.Dispose();//随着工作单元的销毁而销毁
                }
            }
            this.disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        public IDbContextTransaction BeginTransaction()
        {
            var scope = _dbContext.Database.BeginTransaction();
            return scope;
        }

        public List<T> SqlQuery<T>(string sql, object param = null) where T : class
        {
            var con= _dbContext.Database.GetDbConnection();
            if (con.State!= ConnectionState.Open)
            {
                con.Open();
            }
            var list= MysqlDapperReader.SqlQuery<T>(con, sql, param);
            return list;
            //throw new NotImplementedException();
        }

       
        /// <summary>
        /// 动态获取仓储
        /// </summary>
        /// <typeparam name="T"></typeparam>     
        /// <returns></returns>
        public IRepository<T> GetRepository<T>() where T : BaseEntity
        {
            if (_repositories == null)
            {
                _repositories = new Dictionary<Type, object>();
            }

            Type type = typeof(IRepository<T>);
            if (!_repositories.TryGetValue(type, out object repo))
            {
                IRepository<T> newRepo = new Repository<T>(_dbContext);
                _repositories.Add(type, newRepo);
                return newRepo;
            }
            return (IRepository<T>)repo;
        }
        public IQueryable<TEntity> FromSql<TEntity>(string sql, params object[] parameters) where TEntity : BaseEntity => _dbContext.Set<TEntity>().FromSqlRaw(sql, parameters);

        public Task<List<T>> SqlQueryAsync<T>(string sql, object param = null) where T : class
        {
            throw new NotImplementedException();
        }


        //#region Sys Repository
        //private IRepository<Sys_User> _sysUserRep;
        //public IRepository<Sys_User> SysUserRep
        //{
        //    get
        //    {
        //        if (_sysUserRep == null)
        //        {
        //            //var s= HttpContext.Current.Items["currentUser"];
        //            //var s = HttpContext.Current.RequestServices.GetService<IRepository<Sys_User>>();
        //            //HttpContext.RequestServices.GetService<IRepository<Sys_User>>();
        //            _sysUserRep = new Repository<Sys_User>(_dbContext);
        //        }
        //        return _sysUserRep;
        //    }
        //}
        //private IRepository<Sys_Role> _sysRoleRep;
        //public IRepository<Sys_Role> SysRoleRep
        //{
        //    get
        //    {
        //        if (_sysRoleRep == null)
        //        {
        //            _sysRoleRep = new Repository<Sys_Role>(_dbContext);
        //        }
        //        return _sysRoleRep;
        //    }
        //}
        //private IRepository<Sys_Role_User> _sysRoleUserRep;
        //public IRepository<Sys_Role_User> SysRoleUserRep
        //{
        //    get
        //    {
        //        if (_sysRoleUserRep == null)
        //        {
        //            _sysRoleUserRep = new Repository<Sys_Role_User>(_dbContext);
        //        }
        //        return _sysRoleUserRep;
        //    }
        //}

        //private IRepository<Sys_Permission> _sysPermissionRep;
        //public IRepository<Sys_Permission> SysPermissionRep
        //{
        //    get
        //    {
        //        if (_sysPermissionRep == null)
        //        {
        //            _sysPermissionRep = new Repository<Sys_Permission>(_dbContext);
        //        }
        //        return _sysPermissionRep;
        //    }
        //}
        //private IRepository<Sys_Module> _sysModuleRep;
        //public IRepository<Sys_Module> SysModuleRep
        //{
        //    get
        //    {
        //        if (_sysModuleRep == null)
        //        {
        //            _sysModuleRep = new Repository<Sys_Module>(_dbContext);
        //        }
        //        return _sysModuleRep;
        //    }
        //}

        //private IRepository<Sys_Error_Log> _sysErrorLogRep;
        //public IRepository<Sys_Error_Log> SysErrorLogRep
        //{
        //    get
        //    {
        //        if (_sysErrorLogRep == null)
        //        {
        //            _sysErrorLogRep = new Repository<Sys_Error_Log>(_dbContext);
        //        }
        //        return _sysErrorLogRep;
        //    }
        //}

        //private IRepository<Sys_Operation_Log> _sysOperationLogRep;
        //public IRepository<Sys_Operation_Log> SysOperationLogRep
        //{
        //    get
        //    {
        //        if (_sysOperationLogRep == null)
        //        {
        //            _sysOperationLogRep = new Repository<Sys_Operation_Log>(_dbContext);
        //        }
        //        return _sysOperationLogRep;
        //    }
        //} 
        //#endregion

    }
}
